revision:
Click this trigger..to open a modal.
Close a modal by: 1/ clicking off to the side, 2/ clicking the X, or 3/ pressing Escape.
You have opened the first modal!
Now, open the second modal by clicking the link.
Second modal !Nice, the second modal.
<div class="spec">
<p><a href="#" class="modal-trigger" data-modal-id="modal1">
Click this trigger</a>..to open a modal.</p>
<p>Close a modal by: 1/ clicking off to the side, 2/ clicking the
X, or 3/ pressing Escape.</p>
<div class="modal-wrapper" id="modal1">
<section class="modal-window">
<header class="modal-header">
<h3>The first modal</h3>
<button type="button" class="close-modal-button"
aria-label="Close modal window">X</button>
</header>
<p>You have opened the first modal!</p>
<p>Now, open the second modal by clicking the link.</p>
<a href="#" class="modal-trigger" data-modal-id="modal2">
Second modal</a> !</p>
</section>
</div>
<div class="modal-wrapper" id="modal2">
<section class="modal-window">
<header class="modal-header">
<h3>The second modal. 🤯</h3>
<button type="button" class="close-modal-button"
aria-label="Close modal window">X</button>
</header>
<p>Nice, the second modal.</p>
</section>
</div>
</div>
<style>
.modal-wrapper {align-items: center; bottom: 0; display: flex; flex-wrap: wrap;
height: 100vh;justify-content: center;left: 0; opacity: 0;position: fixed;
right: 0; transition: all 0.2s ease-in-out; visibility: hidden; width: 40%;
z-index: 1000;}
.modal-wrapper.visible {opacity: 1;visibility: visible;}
.modal-window {background-image: linear-gradient(red, yellow, black);border-radius:
1vw; box-shadow: 0 .3vw .7vw rgba(0, 0, 0, 0.3); padding: 2vw; transform: scale(0);
transition: 0.2s ease-in-out all;}
.modal-wrapper.visible .modal-window {transform: scale(1);}
.modal-header {align-items: center;border-bottom: 0.2vw solid blue; display: flex;
justify-content: space-between; margin-bottom: 2vw; padding-bottom: 2vw;}
.close-modal-button {border: none; background-color: transparent; color: darkgreen;
cursor: pointer; font-size: 2vw; padding: 0.2vw; }
.close-modal-button:hover {color: black;}
.modal-trigger {color: blue; cursor: pointer; text-decoration: underline;}
</style>
<script>
// Stack of modals
let currentlyOpenModals = [];
const noModalsOpen = () => !currentlyOpenModals.length;
const openModal = modalId => {
const modalWrapper = document.getElementById(modalId);
modalWrapper.classList.add("visible");
currentlyOpenModals.push(modalWrapper);
};
// By definition, it's always the topmost modal that will be closed first
const closeTopmostModal = () => {
if (noModalsOpen()) {
return;
}
const modalWrapper = currentlyOpenModals[currentlyOpenModals.length - 1];
modalWrapper.classList.remove("visible");
currentlyOpenModals.pop();
};
const modalTriggers = document.querySelectorAll(".modal-trigger");
modalTriggers.forEach(modalTrigger => {
modalTrigger.addEventListener("click", clickEvent => {
const trigger = clickEvent.target;
const modalId = trigger.getAttribute("data-modal-id");
openModal(modalId);
});
});
// Otherwise, clicking the content of a modal will propagate the click to the
modal wrapper,
// and that will close the entire thing. That's not what we want!
document.querySelectorAll(".modal-window").forEach(modal => {
modal.addEventListener("click", clickEvent => {
clickEvent.stopPropagation();
});
});
const modalWrappers = document.querySelectorAll(".modal-wrapper");
modalWrappers.forEach(modalWrapper => {
modalWrapper.addEventListener("click", () => {
closeTopmostModal();
});
});
document.querySelectorAll(".close-modal-button").forEach(closeModalButton => {
closeModalButton.addEventListener("click", () => {
closeTopmostModal();
});
});
document.body.addEventListener("keyup", keyEvent => {
if (keyEvent.key === "Escape") {
closeTopmostModal();
}
});
</script>